package com.danco.training.zaneuskaya.faces;

import java.io.Serializable;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.danco.training.zaneuskaya.domain.Account;
import com.danco.training.zaneuskaya.domain.User;
import com.danco.training.zaneuskaya.service.AccountService;
import com.danco.training.zaneuskaya.service.UserService;
import com.danco.training.zaneuskaya.service.exception.UserException;

/**
 * @author Zaneuskaya Aliaksandra
 *
 */

@Component
@Scope("session")
public class AccountBean implements Serializable {

	private static final String ACCOUNT_ALREADY_EXISTS = "Account already exists";

	private static final String ACCOUNT_NOT_FOUND = "Account not found";

	private static final String INVALID_OR_UNKNOWN_CREDENTIALS = "Invalid or unknown credentials.";

	private static final String LOGIN_FAILED_FOR = "Login failed for ";

	private static final String LOGIN_SUCCESSFUL_FOR_USER = "Login successful for user ";

	private static final String LOGIN_SUCCESSFUL_FOR_ACCOUNT = "Login successful for account ";

	private static final String USER_NEW_PAGE = "/user/new?faces-redirect=true";

	private static final String ACCOUNT_DOESN_T_EXIST = "Account doesn't exist";

	private static final String HOME_PAGE_REDIRECT_TRUE = "/home.xhtml?faces-redirect=true";

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static final Logger LOGGER = Logger.getLogger(AccountBean.class);

	@Autowired
	private AccountService accountService;

	@Autowired
	private UserBean userBean;

	@Autowired
	private ProfileBean profileBean;

	@Autowired
	private UserService userService;

	private String email;

	private String password;

	private Account currentAccount;

	private User currentUser;

	public ProfileBean getProfileBean() {
		return profileBean;
	}

	public void setProfileBean(ProfileBean profileBean) {
		this.profileBean = profileBean;
	}

	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Account getCurrentAccount() {
		return currentAccount;
	}

	public void setCurrentAccount(Account currentAccount) {
		this.currentAccount = currentAccount;
	}

	public UserBean getUserBean() {
		return userBean;
	}

	public void setUserBean(UserBean userBean) {
		this.userBean = userBean;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public User getCurrentUser() {
		return currentUser;
	}

	public void setCurrentUser(User currentUser) {
		this.currentUser = currentUser;
	}

	public boolean isLoggedIn() {
		return currentAccount != null && currentUser != null;
	}

	/**
	 * Find account by email and password, find user by account.
	 * 
	 * @return logged in user page
	 */
	public String login() {

		try {
			currentAccount = accountService.getAccountByEmailPassword(email,
					password);
		} catch (UserException e) {
			LOGGER.error(ACCOUNT_NOT_FOUND, e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_WARN,
							LOGIN_FAILED_FOR + currentAccount.getAccountId(),
							INVALID_OR_UNKNOWN_CREDENTIALS));
		}
		if (currentAccount != null) {
			LOGGER.info(LOGIN_SUCCESSFUL_FOR_ACCOUNT
					+ currentAccount.getAccountId());

			currentUser = userService.getUserByAccount(currentAccount);
			if (currentUser != null) {
				currentUser.setOnline(true);
				userService.updateEntity(currentUser);
				userBean.setSelf(currentUser);

				LOGGER.info(LOGIN_SUCCESSFUL_FOR_USER + currentUser.getUserId());

				return profileBean.toSelfPage();

			}
		} else {
			LOGGER.info(LOGIN_FAILED_FOR + currentAccount.getAccountId());

		}
		return null;

	}

	/**
	 * Close the current session
	 * 
	 * @return home page
	 */
	public String logout() {
		if (currentAccount != null && currentUser != null) {
			currentUser = userBean.getSelf();
			currentUser.setOnline(false);
			userService.updateEntity(currentUser);

		}
		LOGGER.debug("invalidating session for "
				+ currentAccount.getAccountId());

		FacesContext.getCurrentInstance().getExternalContext()
				.invalidateSession();

		return HOME_PAGE_REDIRECT_TRUE;

	}

	/**
	 * New account creation, new user based on account creation.
	 * 
	 * @return registration user page
	 */
	public String addAccount() {
		currentAccount = new Account();
		currentAccount.setEmail(email);
		currentAccount.setPassword(password);

		try {
			accountService.createEntity(currentAccount);
		} catch (UserException e) {
			LOGGER.error(ACCOUNT_ALREADY_EXISTS, e);
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_WARN,
							LOGIN_FAILED_FOR + currentAccount.getAccountId(),
							ACCOUNT_ALREADY_EXISTS));
			return HOME_PAGE_REDIRECT_TRUE;
		}

		currentUser = new User();
		try {
			currentUser.setAccount(accountService.getAccountByEmail(email));
		} catch (UserException e) {
			LOGGER.error(e.getMessage());
			return HOME_PAGE_REDIRECT_TRUE;
		}
		currentUser.setOnline(true);
		userService.updateEntity(currentUser);
		userBean.setSelf(currentUser);
		profileBean.setCurrentUser(currentUser);
		return USER_NEW_PAGE;
	}

	public String editAccount() {
		try {
			currentAccount = accountService.getAccountByEmail(email);
		} catch (UserException e) {
			LOGGER.error(e.getMessage(), e);
		}
		if (currentAccount != null) {
			currentAccount.setPassword(password);
			accountService.updateEntity(currentAccount);
		} else {
			LOGGER.info(ACCOUNT_DOESN_T_EXIST);
		}
		return HOME_PAGE_REDIRECT_TRUE;
	}

	public String deleteAccount() {
		try {
			currentAccount = accountService.getAccountByEmailPassword(email,
					password);
		} catch (UserException e) {
			LOGGER.error(e.getMessage());
		}
		currentUser = userService.getUserByAccount(currentAccount);
		userService.deleteEntityById(currentUser.getUserId());
		accountService.deleteEntityById(currentAccount.getAccountId());
		return HOME_PAGE_REDIRECT_TRUE;

	}

}
